# 8.1
T = Any
N = 1
@test Array{T,N} <: DenseArray{T,N} <: AbstractArray{T,N}
@test undef === UndefInitializer()

@test Vector{Int} === Array{Int, 1}
@test Matrix{Int} === Array{Int, 2}

A = Array{Float64, 2}(undef, 2, 3)
dump(A)

B = Array{Int32}(undef, 2,3)
dump(B)

dump(Vector(undef, 3))
dump(Matrix{Int}(undef, (2, 4)))

# 8.1.1
dump([1.2 2.3 3.4 5 6])
dump([1.2 'a' "abc" Some(3)])
dump([1.2; 2.3; 3.4; 5; 6])
dump([1.2, 'a', "abc", Some(3)])
# dump([1, 2, 3; 4])
dump([1 2; 3 4; 5 6])
dump([1.1 2.2 3.3; 4.4 5.5 6.6])
dump(Int32[1 2; 3 4; 5 6])
dump(Float32[1 2 3 4])
# dump(Int64[1.2 3 4.5])
@test  [[1 2] 3 [4 5]] == [1  2  3  4  5]
@test  [1 2 3 [4 5]] == [1  2  3  4  5]
@test [1; 2; [3; 4]] == [1,2,3,4]
#dump([1 2 [3;4]])
#dump([1;2 [3;4]])
@test hcat(1, 2, 3, 4) == [1  2  3  4]
@test vcat(1, 2, 3, 4) == [1,2,3,4]
@test hvcat(2, 1, 2, 3, 4, 5, 6) == [1 2; 3 4; 5 6]
@test hvcat(3, 1,2,3,4,5,6) == [1 2 3; 4 5 6]
# dump(hvcat(7, 1,2,3,4,5,6))
# dump(hvcat(4, 1,2,3,4,5,6))

# 8.1.2
@test A1 = zeros(Int64, 2,3) == [0 0 0; 0 0 0]
@test A2 = zeros(Float64, (2,3)) == [0.0 0.0 0.0; 0.0 0.0 0.0]
@test B1 = ones(Rational, 2,3) == [1//1 1//1 1//1; 1//1 1//1 1//1]
@test  trues((2,3)) == [true true true; true true true]
@test falses(size(B1)) == [false false false; false false false]
C1 = rand(Float64,2,3)
C2 = randn(Float64, (2,3))

# 8.1.3
methods(range)

r1 = range(1, stop=6)
@test r1 == 1:6
foreach(println, r1)

r2 = range(1; stop=6,step=2)
@test r2 == 1:2:5
foreach(println, r2)

r3 = range(1;length=6)
@test r3 == 1:6

r4 = range(1;length=6,step=2)
@test r4 == 1:2:11

for i = 1:2:6     # 其中边界值5不会取到
    println(i)
end
println()
for i ∈ 0.2:1:5.2
    print(i, " ")
end
println()
for i in 1:-0.75:-1
    print(i, " ")
end
println()

@test collect(1:2:6) == [1;3;5]

@test 1:2:0 == []

dump(1:3)
dump(1:2:8)

@test UnitRange <: AbstractUnitRange
@test UnitRange.var.ub == Real
dump(StepRange.body.body)

@test AbstractUnitRange <: OrdinalRange <: AbstractRange <: AbstractArray

dump(0.2:1:5.2)
@test typeof(0.2:1:5.2) == StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}
@test StepRangeLen <: AbstractRange

# 8.1.4
V = rand(4)
[ 0.25*V[i-1] + 0.5*V[i] + 0.25*V[i+1] for i=2:length(V)-1 ]
@test [i*j for i=1:3, j=3:5] == [3 4 5;6 8 10;9 12 15]

[i^2+2j-1.3z for i=1:2, j∈2:5, z in 1:3]
[(i,j) for i=1:3 for j=1:i]
[(i,j) for i=1:3 for j=1:i if i+j == 4]
@test Float32[i*j for i=1:3, j=3:5] == [3.0   4.0   5.0; 6.0   8.0  10.0; 9.0  12.0  15.0]
@time sum(1/n^2 for n=1:100)
@time sum(1/n^2 for n=1:100000)

# 8.2
a = [1 2 3 4 5 6 7]
@test a[1] == 1
@test a[4] == 4
b = rand(2, 3)
@show b[1, 2]
@show b[2, 3]

j = 1:0.3:3
@test j[1] == 1.0
@test j[4] == 1.9
@test j[7] == 2.8

try
    a[8]
catch ex
    @show ex
    @test isa(ex, BoundsError)
end

try
    b[3, 2]
catch ex
    @show ex
    @test isa(ex, BoundsError)
end

c = [1 0 2; 3 0 5]
@test a[end] == 7
@test c[end, end] == 5

@test a[(2*end)>>2] == 3
@test c[end-1, end-2] == 1

a[3] = 30
b[2, 3] = 25

@test a == [1  2  30  4  5  6  7]
@show b


try
    a[4] = 3.8
catch ex
    @show ex
    @test isa(ex, InexactError)
end

# dump(j[2] = 3)

i = CartesianIndex(1,3)
@test i == CartesianIndex{2}((1, 3))

i = CartesianIndex((1,3))
@test i == CartesianIndex{2}((1, 3))

@test a[i] == 30
dump(b[i])
@test c[i] == 2

d = rand(3,4,2,2)
summary(d)

dump(d[2, 3, 1, 2])
i = CartesianIndex(2, 3, 1, 2)
@test d[i] == d[2, 3, 1, 2]

A = reshape(collect(1:12), 3, 4)
@test A[8] == A[2,3]
@test A[length(A)] == A[lastindex(A)] == 12
@test lastindex(A) == 12
@test lastindex(A, 1) == 3
@test lastindex(A, 2) == 4

B = [10 13 16 19; 11 14 17 20; 12 15 18 21]
bli = LinearIndices(B)
@test bli == [1  4  7  10; 2  5  8  11; 3  6  9  12]
@test bli[2, 3] == 8
@test B[2,3] == B[8]
@test B[3,2] == B[bli[3,2]]

bci = CartesianIndices(B)
@test bci[8] == CartesianIndex(2, 3)
@test B[CartesianIndex(2, 3)] == B[8]
@test B[6] == B[bci[6]] == 15

cartesian = CartesianIndices((1:3, 1:2))
@test cartesian[4] == CartesianIndex(1, 2)
linear = LinearIndices((1:3, 1:2))
@test linear[1,2] == 4

p = [1 2 3; 4 5 6]
q = p[:]
@test q == [1,4,2,5,3,6]
@test vec(p) == q

@test CartesianIndices((1:2, 1:3))[3] == CartesianIndex(1, 2)

p = [1 2 3; 4 5 6]
q = vec(p)
q[3] = 10;
@test p[1,2] == 10

m = reshape(p, 3, 2)
m[3,1] = 20
@test p[1,2] == 20

n = reshape(p, 3, :)
n[2,2] = 30
@test p[1,3] == 30

# 8.3
a = reshape(collect(1:12), 3, 4)
@test a == [1  4  7  10; 2  5  8  11; 3  6  9  12]

@test size(a) == (3,4)
i = 1;
while i <= 3            # 对行索引循环
    j = 1;               # 重置到新行的第1列
    while j <= 4         # 对列索引循环
        print(a[i,j], " ")   # 取得对应位置的元素
        j += 1          # 列索引递增
    end
    println("")           # 换行打印
    global i += 1         # 移动到下一行索引   
 end

 for i = 1:size(a,1)
    for j = 1:size(a,2)
        print(a[i,j], " ")
    end
    println("")
end

for i=1:3, j=1:4
    print(a[i, j], " ")
end

r = CartesianIndices((1:3, 1:4))
for k in r
    println(k[1], ",", k[2], " is ", a[k])
end

for i = 1:lastindex(a)
    print(a[i], " ")
end
for i = 1:length(a)
    print(a[i], " ")
end
for i in eachindex(a)
    print(a[i], " ")
end
for x in a
    print(x, " ")
end
for x = a
    print(x, " ")
end
for x ∈ a
    print(x, " ")
end
println()

# 8.4
@test a[2:3, 3:4] == [8 11; 9 12]
@test a[2, 2:end] == [5,8,11]
@test a[2, [2 3; 4 1]] == [5 8; 11 2]
@test a[3, :] == [3,6,9,12]
@test a[:, 3] == [7,8,9]

@test a[[true,false,true], 2] == [4,6]
@test a[[true,false,true],[true,true,true,false]] == [1 4 7; 3 6 9]

x=2;
@test a[[iseven(x), false, !isodd(x)], 2] == [4,6]
@test a[a .> 8] == [9,10,11,12]

@test (@isdefined view) == true
b = view(a, 2:3, 2:3)
@test b == [5 8; 6 9]
@test b[1,1] == 5
b[1,1] = 200;
@test b == [200 8; 6 9]
@test a == [1  4  7  10; 2  200  8  11; 3  6  9  12]

c = @view a[2:3,2:3]
@test c == [200 8; 6 9]
fill!(c, 300)
@test a == [1  4  7  10; 2  300  300  11; 3  300 300 12]


A = rand(10000,10000);
@time A[1000:5000,1000:5000];
@time A[1000:5000,1000:5000];
@time view(A,1000:5000,1000:5000);
@time view(A,1000:5000,1000:5000);
@time view(A,1000:5000,1000:5000);

p = parent(c)
@test p === a

# 8.5
using SparseArrays
@test (@isdefined SparseMatrixCSC)
@test (@isdefined SparseVector)
@test fieldnames(SparseMatrixCSC) == (:m, :n, :colptr, :rowval, :nzval)
@test fieldnames(SparseVector) == (:n, :nzind, :nzval)
@test summary(spzeros(3)) == "3-element SparseVector{Float64,Int64}"
summary(spzeros(Float32, 2,3))

using LinearAlgebra
summary(sparse(I, 3, 5))
summary(sparse(UniformScaling{Int}(10), 3, 4))
dump(SparseMatrixCSC(I, 3, 4))
dump(SparseMatrixCSC(UniformScaling{Float32}(10), 3, 4))

dump(sprand(Bool, 2, 2, 0.5))
dump(sprand(Float64, 3, 0.75))
dump(sprandn(2, 2, 0.75))
dump(sprand(MersenneTwister(1234), 3, 4, 0.3, randexp))

A = Matrix(UniformScaling{Float32}(5),(3,4))
@test A == [5.0  0.0  0.0  0.0; 0.0  5.0  0.0  0.0; 0.0  0.0  5.0  0.0]
B = [1.0, 0.0, 1.0]
a = sparse(A)
b = sparse(B)
summary(a)
summary(b)
a = SparseMatrixCSC(A)
b = SparseVector(B)

AA = collect(a)
BB = collect(b)
@test AA == A
@test BB == B

AA = Matrix(a)
BB = Vector(b)
@test AA == A
@test BB == B


AA = Array(a)
BB = Array(b)
@test AA == A
@test BB == B

@test issparse(b)
@test !issparse(B)

II = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3];
S = sparse(II, J, V)
R = sparsevec(II, V)
sparsevec([1, 3, 1, 2, 2], [true, true, false, false, false])
II = [1, 3, 3, 5]; V = [0.1, 0.2, 0.3, 0.2];
sparsevec(II, V)
sparsevec(II, V, 8, -)
S2 = sparse(II, J, V, 20, 30)

@test size(S) == (5, 18)
@test size(S2) == (20, 30)

Is = [1; 2; 3];
Js = [10; 20; 30];
Vs = [100, 0, 300];
M = sparse(Is, Js, Vs)
@test M[2,20] == 0

MM = dropzeros!(M)
@test nnz(MM) == nnz(M) == 2

@test findall(!iszero, M) == [CartesianIndex(1, 10), CartesianIndex(3, 30)] == findall(!iszero, MM)
@test findnz(M) == ([1, 3], [10, 30], [100, 300]) == findnz(MM)

# 8.6
@test map(round, [1.2, 3.5, 1.7]) == [1.0, 4.0, 2.0]
@test  map(round, (1.2, 3.5, 1.7)) == (1.0, 4.0, 2.0)
@test map(round, 1.1:0.5:3.0) == [1.0, 2.0, 2.0, 3.0]

map(tuple, (1/(i+j) for i=1:2, j=1:2), [1 3; 2 4])
@test map(x -> x * 2, [1, 2, 3]) == [2, 4, 6]

map(x->begin
             if x < 0 && iseven(x)   # 小于0或偶数时返回0
                 return 0
             elseif x == 0           # 0时返回1
                 return 1
             else                  # 其他情况返回原值
                 return x
             end
         end,
         [-2,7,8,0])

map((-2, 7, 8, 0)) do x
                       if x < 0 && iseven(x)   # 小于0或偶数时返回0
                           return 0
                       elseif x == 0           # 0时返回1
                           return 1
                       else                  # 其他情况返回原值
                           return x
                       end
                   end
@test map(~, (1, 2, 3)) == (-2, -3, -4)
@test map(+, [1, 2, 3], [10, 20, 30]) == [11, 22, 33]
@test map(+, [1, 2, 3], [10, 20, 30],[100,200,300]) == [111, 222, 333]

a = zeros(3);
map!(x -> x * 2, a, [1, 2, 3]);
@test a == [2.0, 4.0, 6.0]

x = [1, 2, 3];
map!(+, x, [10,20,30], [100,200,300])
@test x == [110, 220, 330]

@test broadcast(+, (1,2,3), (2,3,4)) == (3, 5, 7)
@test broadcast(x->x*2, (2,3,4)) == (4, 6, 8)
@test broadcast(+, (1,2,3), 2) == (3, 4, 5)
@test broadcast(*, [1,2,3], 2) == [2, 4, 6]
@test map(*, [1,2,3], 2) == [2]
@test broadcast(*, 2, (1,2,3)) == (2, 4, 6)
@test broadcast(*, 2, (1,2,3), 3) == (6, 12, 18)

a = [1 2 3]
b = [1,2,3]
@test broadcast(+, a, b) == [2  3  4; 3  4  5; 4  5  6]
@test map(+, a, b) == [2, 4, 6]

foo = x->x^3
a = [ 2 3 4 5 ]
@test foo.(a) == [8  27  64  125]
sin.(a)
b = [3 2 10 1]
@test min.(a, b) == [2  2  4  1]

c = Tuple(a)
d = Tuple(b)
@test max.(c, d) == (3, 3, 10, 5)

e = Set(a)
f = Set(b)
@test min.(e, f) == [4, 2, 3, 1]

@test (1, 2, 3) .* 2 == (2, 4, 6)

@test [1,2,3] .^ 3 == [1,8,27] == broadcast(^, [1,2,3],3)
@test ((1:10000) .+ 20) .* 7 == 147:7:70140

a = [2 3 4];
@test (a .- 10) == [-8  -7  -6]
@test (a .+ 10) == [12  13  14]
@test (a * 10) == [20  30  40]
@test (a / 4.0) == [0.5  0.75  1.0]
@test  4. \ a == [0.5  0.75  1.0]
@test [1,2,3] == [1,2,3]
@test [1,2,3] != [1,2,5]
@test ([1 2 3] .== [1 2 3]) == [true  true  true]

# 8.7


